﻿using System;
using System.Data;
using System.Data.SqlClient;
using System.Threading.Tasks;
using DB.SchemaSync.Library;
using DB.SchemaSync.Library.Interfaces;
using DB.SchemaSync.Library.Models;

namespace DB.SchemaSync.SqlServer
{

    /// <summary>
    /// sql服务提供者
    /// </summary>
	public partial class SqlServerDbProvider : IDbConnectionProvider
	{
		public ObjectTypeFlags ObjectTypes => ObjectTypeFlags.Tables | ObjectTypeFlags.ForeignKeys | ObjectTypeFlags.Schemas | ObjectTypeFlags.Modules;

		public Func<string, IDbConnection> ConnectionMethod => (connectionString) => new SqlConnection(connectionString);

		public Func<IDbConnection, string, IDbCommand> CommandBuilderMethod => (cn, sql) => new SqlCommand(sql, cn as SqlConnection);

		public Func<IDbCommand, DataColumn, IDbDataParameter> ParameterBuilderMethod => (cmd, col) => new SqlParameter(col.ColumnName, col.DataType);

		public Action<IDbDataParameter, DataRow> AssignParamValueAction => (p, row) => (p as SqlParameter).Value = row[p.ParameterName];


		/// <summary>
		/// 
		/// </summary>
        private string connStr;
        /// <summary>
        /// 设置连接参数
        /// </summary>
        /// <param name="conn"></param>
        public void SetConn(string conn) => this.connStr = conn;

		/// <summary>
		/// 构造函数
		/// </summary>
		public SqlServerDbProvider()
        {
        }

		/// <summary>
		/// 连接参数
		/// </summary>
		/// <param name="conn"></param>
        public SqlServerDbProvider(string conn)
        {
            this.connStr = conn;
        }



		/// <summary>
		/// 获取数据库信息
		/// </summary>
		/// <returns></returns>
        public async Task<Database> GetDatabaseAsync()
        {
            if (string.IsNullOrWhiteSpace(connStr))
            {
				throw new ArgumentException("SQL server 连接字符串必须设置"); 
            }
            using (var cn = ConnectionMethod.Invoke(connStr))
            {
                return await GetDatabaseAsync(cn);
            }

        }



		public async Task<Database> GetDatabaseAsync(IDbConnection connection)
		{
			Database db = new Database();
			db.Schemas = await GetSchemaAsync(connection);
			db.Tables = await GetTablesAsync(connection);
			db.ForeignKeys = await GetForeignKeysAsync(connection);
			db.Modules = await GetModulesAsync(connection);
			db.SeedData = GetSeedData(db.Tables, connection);
			return db;
		}

		public SqlSyntax GetDefaultSyntax()
		{
			return new SqlServerSyntax();
		}
	}
}